home *** CD-ROM | disk | FTP | other *** search
/ The X-Philes (2nd Revision) / The X-Philes Number 1 (1995).iso / xphiles / hp48_2 / star-1_0.tar / ctt.c < prev    next >
C/C++ Source or Header  |  1991-03-22  |  5KB  |  225 lines

  1. /* ctt.c -- Character Transition Tree Operations
  2.  
  3. This file is part of STAR, the Saturn Macro Assembler.
  4.  
  5.    STAR is not distributed by the Free Software Foundation. Do not ask
  6. them for a copy or how to obtain new releases. Instead, send e-mail to
  7. the address below. STAR is merely covered by the GNU General Public
  8. License.
  9.  
  10. Please send your comments, ideas, and bug reports to
  11. Jan Brittenson <bson@ai.mit.edu>
  12.  
  13. */
  14.  
  15.  
  16. /* Copyright (C) 1991 Jan Brittenson.
  17.  
  18.    STAR is free software; you can redistribute it and/or modify it
  19. under the terms of the GNU General Public License as published by the
  20. Free Software Foundation; either version 1, or (at your option) any
  21. later version.
  22.  
  23.    STAR is distributed in the hope that it will be useful, but WITHOUT
  24. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  25. FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  26. for more details.
  27.  
  28.    You should have received a copy of the GNU General Public License
  29. along with STAR; see the file COPYING. If not, to obtain a copy, write
  30. to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,
  31. USA, or send e-mail to bson@ai.mit.edu. */
  32.  
  33.  
  34. #include <stdio.h>
  35. #include "star.h"
  36. #include "symbols.h"
  37. #include "ctt.h"
  38.  
  39.  
  40. /* Allocate ctt root */
  41. static CTT_ROOT *ctt_alloc()
  42. {
  43.   CTT_ROOT *ctt_tmp;
  44.   extern char *malloc();
  45.  
  46.   
  47.   if(!(ctt_tmp = (CTT_ROOT *) malloc(sizeof(CTT_ROOT))))
  48.     fatal("Cannot allocate CTT root, %d bytes", sizeof(CTT_ROOT));
  49.  
  50.   bclear((char *) ctt_tmp, sizeof(CTT_ROOT));
  51.  
  52.   return(ctt_tmp);
  53. }
  54.  
  55.  
  56. /* Allocate ctt node */
  57. static CTT_NODE *ctt_node_alloc()
  58. {
  59.   CTT_NODE *ctt_tmp;
  60.   extern char *malloc();
  61.  
  62.   
  63.   if(!(ctt_tmp = (CTT_NODE *) malloc(sizeof(CTT_NODE))))
  64.     fatal("Cannot allocate CTT node, %d bytes", sizeof(CTT_NODE));
  65.  
  66.   bclear((char *) ctt_tmp, sizeof(CTT_NODE));
  67.  
  68.   return(ctt_tmp);
  69. }
  70.  
  71.  
  72. /* Create new ctt root */
  73. CTT_ROOT *ctt_new()
  74. {
  75.   return(ctt_alloc());
  76. }
  77.  
  78.  
  79. /* Walk characters */
  80. struct sstruct *ctt_find(ctt_root, cpp)
  81.   CTT_ROOT *ctt_root;
  82.   char **cpp;
  83. {
  84.   CTT_NODE *node, *last_match;
  85.   char *str = *cpp, *save = *cpp, *last_match_str;
  86.  
  87.  
  88.   if(!ctt_root || !cpp)
  89.     return((struct sstruct *) 0);
  90.  
  91.   /* Walk */
  92.   for(last_match = NULL, last_match_str = str,
  93.       node = ctt_root->ctt_node[toupper(*str)];
  94.       node; )
  95.     {
  96.       /* Does the current character match the current node? */
  97.       if(node->ctt_c == toupper(*str))
  98.     {
  99.       /* Yes, do we have a binding here? */
  100.       if(node->ctt_binding)
  101.  
  102.         /* Yes, then remember this node */
  103.         last_match = node;
  104.  
  105.       /* Follow match link and move to next char */
  106.       last_match_str = str++;
  107.       node = node->ctt_match;
  108.     }
  109.       else
  110.     /* No, follow fail link */
  111.     node = node->ctt_next;
  112.     }
  113.   
  114.  
  115.   /* Return last match point */
  116.   if(last_match)
  117.     {
  118.       /* Make sure we're not stuck with the initial
  119.        * part of a symbol name, such as "sin" in "sing".
  120.        * The latter should be interpreted as sing, rather
  121.        * sin(g). The exception is when the operator name isn't
  122.        * a valid symbol name, e.g. "0x40".
  123.        */
  124.       if(issym(*last_match_str) && issym(last_match_str[1]) &&
  125.      isisym(*save))
  126.       
  127.     return((struct sstruct *) 0);
  128.  
  129.       *cpp = last_match_str+1;
  130.       return(last_match->ctt_binding);
  131.     }
  132.   else
  133.     {
  134.       *cpp = save;
  135.       return((SYM_NODE *) 0);
  136.     }
  137. }
  138.  
  139.  
  140. /* Convert string to virgin match list */
  141. static CTT_NODE *ctt_make_match(str, binding)
  142.   char *str;
  143.   SYM_NODE *binding;
  144. {
  145.   CTT_NODE *start_node, *node, *new_node;
  146.  
  147.   start_node = ctt_node_alloc();
  148.  
  149.   for(node = start_node, start_node->ctt_c = *str++; *str; node = new_node)
  150.     {
  151.       new_node = ctt_node_alloc();
  152.  
  153.       new_node->ctt_c = *str++;
  154.       node->ctt_match = new_node;
  155.     }
  156.  
  157.   node->ctt_binding = binding;
  158.  
  159.   return(start_node);
  160. }
  161.  
  162.  
  163. /* Add string to tree */
  164. void ctt_add(ctt_root, str, binding)
  165.   CTT_ROOT *ctt_root;
  166.   char *str;
  167.   SYM_NODE *binding;
  168. {
  169.   CTT_NODE *node;
  170.  
  171.   if(!ctt_root)
  172.     return;
  173.  
  174.   
  175.   /* Walk until we're at the link point */
  176.   if(!(node = ctt_root->ctt_node[*str]))
  177.     {
  178.       /* Virgin tree, initialize */
  179.       ctt_root->ctt_node[*str] = ctt_make_match(str, binding);
  180.       return;
  181.     }
  182.  
  183.   /* If we drop out of the loop, the string cannot be added */
  184.   while(*str)
  185.     {
  186.       /* Does the current character match the current node? */
  187.       if(node->ctt_c == *str)
  188.     {
  189.       /* Yes, do we have a match link? */
  190.       if(!node->ctt_match)
  191.         {
  192.           /* No - link up here */
  193.           if(*++str)
  194.         node->ctt_match = ctt_make_match(str, binding);
  195.           else
  196.         node->ctt_binding = binding;
  197.  
  198.           return;
  199.         }
  200.  
  201.       /* Yes, follow it and move to next char.
  202.        * See if end of string */
  203.       if(!*++str)
  204.         {
  205.           /* This means we're entering a substring, so we
  206.            * just rebind the node.
  207.            */
  208.           node->ctt_binding = binding;
  209.           return;
  210.         }
  211.       node = node->ctt_match;
  212.     }
  213.       else
  214.     /* No, follow fail link */
  215.     if(node->ctt_next)
  216.       node = node->ctt_next;
  217.     else
  218.       {
  219.         /* No fail link - link up here */
  220.         node->ctt_next = ctt_make_match(str, binding);
  221.         return;
  222.       }
  223.     }
  224. }
  225.